using System.Collections;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using UnityEngine;

namespace NGUI
{
    [RequireComponent(typeof(CanvasGroup))]
    public class Hidable : RectBehaviour
    {
        [Range(0, 1)]
        public float hiddenAlpha;
        [Range(0, 1)]
        public float shownAlpha = 1;
        public float translation = 0.1f;
        public bool modifyInteractable = true;
        public bool modifyBlockRaycasts = true;

        public bool shown = true;
        
        private CanvasGroup CanvasGroup => GetComponent<CanvasGroup>();
        private Tween _currentTween;

        protected virtual void Start()
        {
            shown = !shown; // 防止状态检查导致不进行显示、隐藏
            if (!shown)
                ShowImmediate();
            else
                HideImmediate();
        }

        public virtual void Show()
        {
            if (shown)
                return;
            shown = true;
            if (_currentTween is { active: true })
                _currentTween.Kill();
            _currentTween = CanvasGroup.DOFade(shownAlpha, translation);
            SetInteractions(true);
        }

        public virtual void ShowImmediate()
        {
            if (shown)
                return;
            shown = true;
            CanvasGroup.alpha = shownAlpha;
            SetInteractions(true);
        }

        public virtual void Hide()
        {
            if (!shown)
                return;
            shown = false;
            if (_currentTween is { active: true })
                _currentTween.Kill();
            _currentTween = CanvasGroup.DOFade(hiddenAlpha, translation);
            SetInteractions(false);
        }

        public virtual void HideDestroy()
        {
            Hide();
            StartCoroutine(WaitDestroy());
        }

        public virtual void HideImmediate()
        {
            if (!shown)
                return;
            shown = false;
            CanvasGroup.alpha = hiddenAlpha;
            SetInteractions(false);
        }

        protected virtual void SetInteractions(bool shown)
        {
            if (modifyInteractable)
                CanvasGroup.interactable = shown;
            if (modifyBlockRaycasts)
                CanvasGroup.blocksRaycasts = shown;
        }

        public virtual void Set(bool shown)
        {
            if (shown)
                Show();
            else
                Hide();
        }
        
        public virtual void SetImmediate(bool shown)
        {
            if (shown)
                ShowImmediate();
            else
                HideImmediate();
        }

        public virtual void Toggle()
        {
            Set(!shown);
        }

        public virtual void ToggleImmediate()
        {
            SetImmediate(!shown);
        }

        private IEnumerator WaitDestroy()
        {
            yield return new WaitForSeconds(translation);
            Destroy(gameObject);
        }
    }
    // IDE在asmdef中会找不到类似DOFade的扩展方法
#if UNITY_EDITOR
    public static class DOTweenIDEFix
    {
        public static TweenerCore<float, float, FloatOptions> DOFade(this CanvasGroup target, float endValue, float duration)
        {
            var t = DOTween.To(() => target.alpha, x => target.alpha = x, endValue, duration);
            t.SetTarget(target);
            return t;
        }
    }
#endif
}